iOS runtime浅析Property和Ivar

Property

propertyObjective-C的一个语法糖,能帮助你声明成员变量(ivar)(自动声明的变量名前面会加下划线)+自动生成对应属性特性(atomic/nonatomic/copy/strong/weak/assign...)settergetter

通常我们在编写iOS程序的时候声明类的成员变量,习惯使用property

1
2
3
4
5
6
7
8
9
10
11
12
//
// GMYTestObject.h
// ObjectInspector
//
// Created by miaoyou.gmy on 2017/2/22.
// Copyright © 2017年 miaoyou.gmy. All rights reserved.
//
@interface GMYTestObject : NSObject
@property (nonatomic, assign) NSUInteger index;
@property (nonatomic, copy) NSString *str;
@property (nonatomic, copy) NSArray *array;
@end

对应自动声明的_index_str_array

若想声明private的成员变量要借助Class Extensions在原有的实现文件中添加变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//
// GMYTestObject.m
// ObjectInspector
//
// Created by miaoyou.gmy on 2017/2/22.
// Copyright © 2017年 miaoyou.gmy. All rights reserved.
//

#import "GMYTestObject.h"

@interface GMYTestObject ()
@property (nonatomic, copy) NSString *testStr;
@property (nonatomic, assign) CGFloat margin;
@property (nonatomic, copy) NSDictionary *dict;
@end

@implementation GMYTestObject
@end

这个技巧可以参阅Class Extensions Extend the Internal Implementation

题外话

property在早些年是不支持声明类变量的。直到2016年Xcode8发布和更新了LLVM,才支持。
WWDC 2016 Session 405 What’s New in LLVM

From the Xcode 8 release notes:

Objective-C now supports class properties, which interoperate with Swift type properties. They are declared as: @property (class) NSString *someStringProperty;. They are never synthesized. (23891898)

额外要注意是,使用property声明类变量是不会自动合成settergetter 的。They are never synthesized.

要使用这个特性的具体实践是:
.h头文件中声明

1
2
3
4
5
6
7
8
9
10
11
12
//
// GMYTestObject.h
// ObjectInspector
//
// Created by miaoyou.gmy on 2017/2/22.
// Copyright © 2017年 miaoyou.gmy. All rights reserved.
//

#import <Foundation/Foundation.h>
@interface GMYTestObject : NSObject
@property (class, nonatomic, assign) NSUInteger instanceCount;
@end

.m实现文件中声明settergetter + 声明static 同类型类变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//
// GMYTestObject.m
// ObjectInspector
//
// Created by miaoyou.gmy on 2017/2/22.
// Copyright © 2017年 miaoyou.gmy. All rights reserved.
//

#import "GMYTestObject.h"
@implementation GMYTestObject
static NSUInteger _instanceCount = 0;
+ (NSUInteger)instanceCount{
return _instanceCount;
}

+ (void)setInstanceCount:(NSUInteger)instanceCount{
_instanceCount = instanceCount; // 重复声明一个类变量是为了实现setter,加_是自有成员变量的传统命名规则
}
@end

Ivar

PropertyIvar+synthesized setter + synthesized getter 的语法糖
Ivar指的就是instance variables

1
2
3
4
5
6
@interface GMYTestObject : NSObject{
@public
NSUInteger _index;
NSString *_str;
NSArray *_array;
}

没有自动合成的settergetter方法。在OOP的封装概念下显得不那么讨喜,渐渐被Property取代。

“原始”的Ivar声明方式也有不少好处:why-would-you-use-an-ivar

runtime

我们再来聊聊如何借助iOS的动态性,获取一个对象的所有成员变量。

<objc/runtime.h>

1
2
3
4
// Describes the properties declared by a class.

OBJC_EXPORT objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
1
2
3
4
// Describes the instance variables declared by a class.

OBJC_EXPORT Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);

根据PropertyIvar 的关系可知。我们使用class_copyIvarList就能获取到所有对象成员变量,包括使用原始声明方式声明的变量。

我们再看看有什么和Ivar相关的API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Returns the name of an instance variable.
OBJC_EXPORT const char *ivar_getName(Ivar v);

//Returns the type string of an instance variable.
OBJC_EXPORT const char *ivar_getTypeEncoding(Ivar v);

//Returns the offset of an instance variable.
OBJC_EXPORT ptrdiff_t ivar_getOffset(Ivar v);

//Reads the value of an instance variable in an object.
OBJC_EXPORT id object_getIvar(id obj, Ivar ivar);

//Sets the value of an instance variable in an object.
OBJC_EXPORT void object_setIvar(id obj, Ivar ivar, id value);

定义GMYTestObject作用测试各个类型的成员变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//
// GMYTestObject.h
// ObjectInspector
//
// Created by miaoyou.gmy on 2017/2/22.
// Copyright © 2017年 miaoyou.gmy. All rights reserved.
//

#import <Foundation/Foundation.h>

typedef enum{
TestA,
TestB,
TestC
}TestEnum;

typedef struct{
float x,y;
}pointNode;

@interface CustomizeObject : NSObject
@property (nonatomic) NSString *name;
@property (nonatomic) NSUInteger age;
@end

@interface GMYTestObject : NSObject
@property (nonatomic) char aChar;
@property (nonatomic) int anInt;
@property (nonatomic) short aShort;
@property (nonatomic) long aLong;
@property (nonatomic) long long aLongLong;
@property (nonatomic) unsigned char anUnsignedChar;
@property (nonatomic) unsigned int anUnsignedInt;
@property (nonatomic) unsigned short anUnsignedShort;
@property (nonatomic) unsigned long anUnsignedLong;
@property (nonatomic) unsigned long long anUnsignedLongLong;
@property (nonatomic) float aFloat;
@property (nonatomic) double aDouble;
@property (nonatomic) BOOL aBooL;
@property (nonatomic) Boolean aBoolean;
@property (nonatomic) bool abool;
@property (nonatomic) char* aCharStar;
@property (nonatomic) int* aIntStar;
@property (nonatomic) void aVoid;
@property (nonatomic) TestEnum aEnum;
@property (nonatomic) pointNode aNode;
@property (nonatomic) SEL aSEL;
@property (nonatomic) id aId;
@property (nonatomic) Class aClass;
@property (nonatomic) NSArray<NSString *> *array;
@property (nonatomic) NSArray<CustomizeObject *> *customizeArray;
@property (nonatomic) NSDictionary *dictionary;
@property (nonatomic) NSSet *aSet;
@property (nonatomic) NSRange range;
@end

使用ivar_getNameivar_getTypeEncoding 打印结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
c _aChar
C _anUnsignedChar
c _aBooL
C _aBoolean
B _abool
s _aShort
S _anUnsignedShort
i _anInt
I _anUnsignedInt
f _aFloat
i _aEnum
q _aLong
q _aLongLong
Q _anUnsignedLong
Q _anUnsignedLongLong
d _aDouble
* _aCharStar
^i _aIntStar
{?="x"f"y"f} _aNode
: _aSEL
@ _aId
# _aClass
@"NSArray" _array
@"NSArray" _customizeArray
@"NSDictionary" _dictionary
@"NSSet" _aSet
{_NSRange="location"Q"length"Q} _range

@note For possible values, see Objective-C Runtime Programming Guide > Type Encodings.

我们还可以更加直观的查看

使用clang rewrite-objc GMYTestObject.m。因为内容过多,这里只放最重要的内容。我们可以清晰的看到 property声明的成员变量是如何定义在C++文件中的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#ifndef _REWRITER_typedef_GMYTestObject
#define _REWRITER_typedef_GMYTestObject
typedef struct objc_object GMYTestObject;
typedef struct {} _objc_exc_GMYTestObject;
#endif

extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aId;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aBoolean;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_dictionary;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aEnum;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_anUnsignedChar;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_anInt;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aFloat;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_abool;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aSEL;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aNode;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_customizeArray;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aLongLong;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aChar;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aCharStar;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aDouble;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_anUnsignedShort;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_range;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aLong;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_anUnsignedLong;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_array;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aIntStar;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aBooL;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_anUnsignedInt;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aSet;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aShort;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_anUnsignedLongLong;
extern "C" unsigned long OBJC_IVAR_$_GMYTestObject$_aClass;
struct GMYTestObject_IMPL {
struct NSObject_IMPL NSObject_IVARS;
char _aChar;
unsigned char _anUnsignedChar;
BOOL _aBooL;
Boolean _aBoolean;
bool _abool;
short _aShort;
unsigned short _anUnsignedShort;
int _anInt;
unsigned int _anUnsignedInt;
float _aFloat;
TestEnum _aEnum;
long _aLong;
long long _aLongLong;
unsigned long _anUnsignedLong;
unsigned long long _anUnsignedLongLong;
double _aDouble;
char *_aCharStar;
int *_aIntStar;
pointNode _aNode;
SEL _aSEL;
id _aId;
Class _aClass;
NSArray<NSString *> *_array;
NSArray<CustomizeObject *> *_customizeArray;
NSDictionary *_dictionary;
NSSet *_aSet;
NSRange _range;
};

// @property (nonatomic) char aChar;
// @property (nonatomic) int anInt;
// @property (nonatomic) short aShort;
// @property (nonatomic) long aLong;
// @property (nonatomic) long long aLongLong;
// @property (nonatomic) unsigned char anUnsignedChar;
// @property (nonatomic) unsigned int anUnsignedInt;
// @property (nonatomic) unsigned short anUnsignedShort;
// @property (nonatomic) unsigned long anUnsignedLong;
// @property (nonatomic) unsigned long long anUnsignedLongLong;
// @property (nonatomic) float aFloat;
// @property (nonatomic) double aDouble;
// @property (nonatomic) BOOL aBooL;
// @property (nonatomic) Boolean aBoolean;
// @property (nonatomic) bool abool;
// @property (nonatomic) char* aCharStar;
// @property (nonatomic) int* aIntStar;
// @property (nonatomic) void aVoid;
// @property (nonatomic) TestEnum aEnum;
// @property (nonatomic) pointNode aNode;
// @property (nonatomic) SEL aSEL;
// @property (nonatomic) id aId;
// @property (nonatomic) Class aClass;
// @property (nonatomic) NSArray<NSString *> *array;
// @property (nonatomic) NSArray<CustomizeObject *> *customizeArray;
// @property (nonatomic) NSDictionary *dictionary;
// @property (nonatomic) NSSet *aSet;
// @property (nonatomic) NSRange range;
/* @end */


// @implementation GMYTestObject
// @dynamic aVoid;

static instancetype _I_GMYTestObject_init(GMYTestObject * self, SEL _cmd) {
self = ((GMYTestObject *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("GMYTestObject"))}, sel_registerName("init"));
if(self){

}
return self;
}




static char _I_GMYTestObject_aChar(GMYTestObject * self, SEL _cmd) { return (*(char *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aChar)); }
static void _I_GMYTestObject_setAChar_(GMYTestObject * self, SEL _cmd, char aChar) { (*(char *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aChar)) = aChar; }

static int _I_GMYTestObject_anInt(GMYTestObject * self, SEL _cmd) { return (*(int *)((char *)self + OBJC_IVAR_$_GMYTestObject$_anInt)); }
static void _I_GMYTestObject_setAnInt_(GMYTestObject * self, SEL _cmd, int anInt) { (*(int *)((char *)self + OBJC_IVAR_$_GMYTestObject$_anInt)) = anInt; }

static short _I_GMYTestObject_aShort(GMYTestObject * self, SEL _cmd) { return (*(short *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aShort)); }
static void _I_GMYTestObject_setAShort_(GMYTestObject * self, SEL _cmd, short aShort) { (*(short *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aShort)) = aShort; }

static long _I_GMYTestObject_aLong(GMYTestObject * self, SEL _cmd) { return (*(long *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aLong)); }
static void _I_GMYTestObject_setALong_(GMYTestObject * self, SEL _cmd, long aLong) { (*(long *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aLong)) = aLong; }

static long long _I_GMYTestObject_aLongLong(GMYTestObject * self, SEL _cmd) { return (*(long long *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aLongLong)); }
static void _I_GMYTestObject_setALongLong_(GMYTestObject * self, SEL _cmd, long long aLongLong) { (*(long long *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aLongLong)) = aLongLong; }

static unsigned char _I_GMYTestObject_anUnsignedChar(GMYTestObject * self, SEL _cmd) { return (*(unsigned char *)((char *)self + OBJC_IVAR_$_GMYTestObject$_anUnsignedChar)); }
static void _I_GMYTestObject_setAnUnsignedChar_(GMYTestObject * self, SEL _cmd, unsigned char anUnsignedChar) { (*(unsigned char *)((char *)self + OBJC_IVAR_$_GMYTestObject$_anUnsignedChar)) = anUnsignedChar; }

static unsigned int _I_GMYTestObject_anUnsignedInt(GMYTestObject * self, SEL _cmd) { return (*(unsigned int *)((char *)self + OBJC_IVAR_$_GMYTestObject$_anUnsignedInt)); }
static void _I_GMYTestObject_setAnUnsignedInt_(GMYTestObject * self, SEL _cmd, unsigned int anUnsignedInt) { (*(unsigned int *)((char *)self + OBJC_IVAR_$_GMYTestObject$_anUnsignedInt)) = anUnsignedInt; }

static unsigned short _I_GMYTestObject_anUnsignedShort(GMYTestObject * self, SEL _cmd) { return (*(unsigned short *)((char *)self + OBJC_IVAR_$_GMYTestObject$_anUnsignedShort)); }
static void _I_GMYTestObject_setAnUnsignedShort_(GMYTestObject * self, SEL _cmd, unsigned short anUnsignedShort) { (*(unsigned short *)((char *)self + OBJC_IVAR_$_GMYTestObject$_anUnsignedShort)) = anUnsignedShort; }

static unsigned long _I_GMYTestObject_anUnsignedLong(GMYTestObject * self, SEL _cmd) { return (*(unsigned long *)((char *)self + OBJC_IVAR_$_GMYTestObject$_anUnsignedLong)); }
static void _I_GMYTestObject_setAnUnsignedLong_(GMYTestObject * self, SEL _cmd, unsigned long anUnsignedLong) { (*(unsigned long *)((char *)self + OBJC_IVAR_$_GMYTestObject$_anUnsignedLong)) = anUnsignedLong; }

static unsigned long long _I_GMYTestObject_anUnsignedLongLong(GMYTestObject * self, SEL _cmd) { return (*(unsigned long long *)((char *)self + OBJC_IVAR_$_GMYTestObject$_anUnsignedLongLong)); }
static void _I_GMYTestObject_setAnUnsignedLongLong_(GMYTestObject * self, SEL _cmd, unsigned long long anUnsignedLongLong) { (*(unsigned long long *)((char *)self + OBJC_IVAR_$_GMYTestObject$_anUnsignedLongLong)) = anUnsignedLongLong; }

static float _I_GMYTestObject_aFloat(GMYTestObject * self, SEL _cmd) { return (*(float *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aFloat)); }
static void _I_GMYTestObject_setAFloat_(GMYTestObject * self, SEL _cmd, float aFloat) { (*(float *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aFloat)) = aFloat; }

static double _I_GMYTestObject_aDouble(GMYTestObject * self, SEL _cmd) { return (*(double *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aDouble)); }
static void _I_GMYTestObject_setADouble_(GMYTestObject * self, SEL _cmd, double aDouble) { (*(double *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aDouble)) = aDouble; }

static BOOL _I_GMYTestObject_aBooL(GMYTestObject * self, SEL _cmd) { return (*(BOOL *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aBooL)); }
static void _I_GMYTestObject_setABooL_(GMYTestObject * self, SEL _cmd, BOOL aBooL) { (*(BOOL *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aBooL)) = aBooL; }

static Boolean _I_GMYTestObject_aBoolean(GMYTestObject * self, SEL _cmd) { return (*(Boolean *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aBoolean)); }
static void _I_GMYTestObject_setABoolean_(GMYTestObject * self, SEL _cmd, Boolean aBoolean) { (*(Boolean *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aBoolean)) = aBoolean; }

static bool _I_GMYTestObject_abool(GMYTestObject * self, SEL _cmd) { return (*(bool *)((char *)self + OBJC_IVAR_$_GMYTestObject$_abool)); }
static void _I_GMYTestObject_setAbool_(GMYTestObject * self, SEL _cmd, bool abool) { (*(bool *)((char *)self + OBJC_IVAR_$_GMYTestObject$_abool)) = abool; }

static char * _I_GMYTestObject_aCharStar(GMYTestObject * self, SEL _cmd) { return (*(char **)((char *)self + OBJC_IVAR_$_GMYTestObject$_aCharStar)); }
static void _I_GMYTestObject_setACharStar_(GMYTestObject * self, SEL _cmd, char *aCharStar) { (*(char **)((char *)self + OBJC_IVAR_$_GMYTestObject$_aCharStar)) = aCharStar; }

static int * _I_GMYTestObject_aIntStar(GMYTestObject * self, SEL _cmd) { return (*(int **)((char *)self + OBJC_IVAR_$_GMYTestObject$_aIntStar)); }
static void _I_GMYTestObject_setAIntStar_(GMYTestObject * self, SEL _cmd, int *aIntStar) { (*(int **)((char *)self + OBJC_IVAR_$_GMYTestObject$_aIntStar)) = aIntStar; }

static TestEnum _I_GMYTestObject_aEnum(GMYTestObject * self, SEL _cmd) { return (*(TestEnum *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aEnum)); }
static void _I_GMYTestObject_setAEnum_(GMYTestObject * self, SEL _cmd, TestEnum aEnum) { (*(TestEnum *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aEnum)) = aEnum; }

static pointNode _I_GMYTestObject_aNode(GMYTestObject * self, SEL _cmd) { return (*(pointNode *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aNode)); }
static void _I_GMYTestObject_setANode_(GMYTestObject * self, SEL _cmd, pointNode aNode) { (*(pointNode *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aNode)) = aNode; }

static SEL _I_GMYTestObject_aSEL(GMYTestObject * self, SEL _cmd) { return (*(SEL *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aSEL)); }
static void _I_GMYTestObject_setASEL_(GMYTestObject * self, SEL _cmd, SEL aSEL) { (*(SEL *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aSEL)) = aSEL; }

static id _I_GMYTestObject_aId(GMYTestObject * self, SEL _cmd) { return (*(id *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aId)); }
static void _I_GMYTestObject_setAId_(GMYTestObject * self, SEL _cmd, id aId) { (*(id *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aId)) = aId; }

static Class _I_GMYTestObject_aClass(GMYTestObject * self, SEL _cmd) { return (*(Class *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aClass)); }
static void _I_GMYTestObject_setAClass_(GMYTestObject * self, SEL _cmd, Class aClass) { (*(Class *)((char *)self + OBJC_IVAR_$_GMYTestObject$_aClass)) = aClass; }

static NSArray<NSString *> * _I_GMYTestObject_array(GMYTestObject * self, SEL _cmd) { return (*(NSArray<NSString *> **)((char *)self + OBJC_IVAR_$_GMYTestObject$_array)); }
static void _I_GMYTestObject_setArray_(GMYTestObject * self, SEL _cmd, NSArray<NSString *> *array) { (*(NSArray<NSString *> **)((char *)self + OBJC_IVAR_$_GMYTestObject$_array)) = array; }

static NSArray<CustomizeObject *> * _I_GMYTestObject_customizeArray(GMYTestObject * self, SEL _cmd) { return (*(NSArray<CustomizeObject *> **)((char *)self + OBJC_IVAR_$_GMYTestObject$_customizeArray)); }
static void _I_GMYTestObject_setCustomizeArray_(GMYTestObject * self, SEL _cmd, NSArray<CustomizeObject *> *customizeArray) { (*(NSArray<CustomizeObject *> **)((char *)self + OBJC_IVAR_$_GMYTestObject$_customizeArray)) = customizeArray; }

static NSDictionary * _I_GMYTestObject_dictionary(GMYTestObject * self, SEL _cmd) { return (*(NSDictionary **)((char *)self + OBJC_IVAR_$_GMYTestObject$_dictionary)); }
static void _I_GMYTestObject_setDictionary_(GMYTestObject * self, SEL _cmd, NSDictionary *dictionary) { (*(NSDictionary **)((char *)self + OBJC_IVAR_$_GMYTestObject$_dictionary)) = dictionary; }

static NSSet * _I_GMYTestObject_aSet(GMYTestObject * self, SEL _cmd) { return (*(NSSet **)((char *)self + OBJC_IVAR_$_GMYTestObject$_aSet)); }
static void _I_GMYTestObject_setASet_(GMYTestObject * self, SEL _cmd, NSSet *aSet) { (*(NSSet **)((char *)self + OBJC_IVAR_$_GMYTestObject$_aSet)) = aSet; }

static NSRange _I_GMYTestObject_range(GMYTestObject * self, SEL _cmd) { return (*(NSRange *)((char *)self + OBJC_IVAR_$_GMYTestObject$_range)); }
static void _I_GMYTestObject_setRange_(GMYTestObject * self, SEL _cmd, NSRange range) { (*(NSRange *)((char *)self + OBJC_IVAR_$_GMYTestObject$_range)) = range; }
// @end

我们都可以看到property 自动生成的gettersetter的实现和声明成员变量的命名符号,是不是很受冲击 - -+